package com.btshop.file.util;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import com.util.DateUtil;

import lombok.extern.slf4j.Slf4j;
import sun.misc.BASE64Decoder;

/**
 * @ClassName: OSSUtil
 * @description: OSS操作工具类
 * @author: 李东
 * @Date: 2020-7-16 16:11
 */
@Slf4j
@Configuration
public class OSSUtil {

    /***************************************** 加载OSS配置 ********************************************/

    @Value("${oss.endpint}")
    public String endpint;
    @Value("${oss.accessKeyId}")
    public String accessKeyId;
    @Value("${oss.accessKeySecret}")
    public String accessKeySecret;
    @Value("${oss.bucketName}")
    public String bucketName;
    @Value("${oss.baseUrl}")
    public String baseUrl;


    /***************************************** OSS操作方法 ********************************************/

    /**
     * @description: 创建存储空间 Bucket
     * @Param: [bucketName]
     * @return: java.lang.String
     * @author: 李东
     * @time: 2020-7-16 16:32
     **/
    public String createBucketName(String bucketName) {
        OSS ossclient = new OSSClientBuilder().build(endpint, accessKeyId, accessKeySecret);
        // 存储空间
        final String bucketNames = bucketName;
        if (!ossclient.doesBucketExist(bucketName)) {
            // 创建存储空间
            Bucket bucket = ossclient.createBucket(bucketName);
            log.info("【file-service】 创建存储空间【{}】成功！", bucket.getName());
            return bucket.getName();
        }
        return bucketNames;
    }

    /**
     * @description: 删除存储空间 Bucket
     * @Param: [bucketName]
     * @return: void
     * @author: 李东
     * @time: 2020-7-16 16:34
     **/
    public void deleteBucket(String bucketName) {
        OSS ossclient = new OSSClientBuilder().build(endpint, accessKeyId, accessKeySecret);
        ossclient.deleteBucket(bucketName);
        log.info("【file-service】 删除存储空间【{}】成功！", bucketName);
    }

    /**
     * @description: 创建文件夹
     * @Param: [bucketName, folder]
     * @return: java.lang.String
     * @author: 李东
     * @time: 2020-7-16 16:35
     **/
    public String createFolder(String bucketName, String folder) {
        OSS ossclient = new OSSClientBuilder().build(endpint, accessKeyId, accessKeySecret);
        // 文件夹名
        final String keySuffixWithSlash = folder;
        // 判断文件夹是否存在，不存在则创建
        if (!ossclient.doesObjectExist(bucketName, keySuffixWithSlash)) {
            // 创建文件夹
            ossclient.putObject(bucketName, keySuffixWithSlash,
                    new ByteArrayInputStream(new byte[0]));
            log.info("【file-service】 创建文件夹【{}】成功！", folder);
            // 得到文件夹名
            OSSObject object = ossclient.getObject(bucketName, keySuffixWithSlash);
            String fileDir = object.getKey();
            return fileDir;
        }
        return keySuffixWithSlash;
    }

    /**
     * @description: 根据key删除OSS服务器上的文件
     * @Param: [bucketName, folder, key]
     * @return: void
     * @author: 李东
     * @time: 2020-7-16 16:37
     **/
    public void deleteFile(String bucketName, String folder, String key) {
        OSS ossclient = new OSSClientBuilder().build(endpint, accessKeyId, accessKeySecret);
        ossclient.deleteObject(bucketName, folder + key);
        log.info("【file-service】删除{}下的文件{}{}成功！", bucketName, folder, key);
    }

    /**
     * @description: 根据文件url删除OSS服务器上的文件
     * @Param: [url]
     * @return: void
     * @author: 李东
     * @time: 2020-7-17 12:30
     **/
    public void deleteFile(String url) {
        OSS ossclient = new OSSClientBuilder().build(endpint, accessKeyId, accessKeySecret);
        String replaceUrl = url.replace(baseUrl+"/", "");
        log.info("replaceUrl is {}",replaceUrl);
        ossclient.deleteObject(bucketName, replaceUrl);
        log.info("【file-service】删除{}下的文件{}成功！", bucketName, replaceUrl);
    }


    /**
     * @description: OSS 文件上传
     * @Param: [file]
     * @return: java.lang.String 文件上传返回的url
     * @author: 李东
     * @time: 2020-7-10 15:32
     **/
    public String upload(File file) {
        log.info("【file-service】文件上传OSS开始,文件名:{}", file.getName());
        OSS ossclient = new OSSClientBuilder().build(endpint, accessKeyId, accessKeySecret);
        // 文件上传成功后返回的url
        String resUrl = "";
        try {
            // 容器不存在，就创建
            if (!ossclient.doesBucketExist(bucketName)) {
                ossclient.createBucket(bucketName);
                CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
                createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
                ossclient.createBucket(createBucketRequest);
            }
            // 创建文件路径
            String fileUrl = "files/" + file.getName();
            // 上传文件
            PutObjectResult result = ossclient.putObject(bucketName, fileUrl, file);
            // 设置权限 这里是公开读
            ossclient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
            if (null != result) {
                String realUrl = baseUrl + "/" + fileUrl;
                log.info("【file-service】文件上传OSS成功,文件URL地址:{}", realUrl);
                resUrl = realUrl;
            }
        } catch (Exception e) {
            log.error("【file-service】 OSS文件上传异常,异常信息:{}", e);
            throw e;
        } finally {
            ossclient.shutdown();
        }
        return resUrl;
    }


    /**
     * @description: OSS 文件上传
     * @Param: [bytes, fileName]
     * @return: java.lang.String
     * @author: 李东
     * @time: 2020-7-16 16:53
     **/
    public String upload(String bytes, String fileName) {
        log.info("【file-service】文件上传OSS开始,文件名:{}", fileName);
        OSS ossclient = new OSSClientBuilder().build(endpint, accessKeyId, accessKeySecret);
        // 文件上传成功后返回的url
        String resUrl = "";
        try {
            // 容器不存在，就创建
            if (!ossclient.doesBucketExist(bucketName)) {
                ossclient.createBucket(bucketName);
                CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
                createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
                ossclient.createBucket(createBucketRequest);
            }
            // 创建文件路径
            String fileUrl = "files/" + fileName;
            // 上传文件
            byte[] buffer = new BASE64Decoder().decodeBuffer(bytes);
            ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer);
            PutObjectResult result = ossclient.putObject(bucketName, fileUrl, inputStream);
            // 设置权限 这里是公开读
            ossclient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
            if (null != result) {
                String realUrl = baseUrl + "/" + fileUrl;
                log.info("【file-service】文件上传OSS成功,文件URL地址:{}", realUrl);
                resUrl = realUrl;
            }
        } catch (Exception e) {
            log.error("【file-service】 OSS文件上传异常,异常信息:{}", e);
            throw new RuntimeException("OSS文件上传异常！");
        } finally {
            ossclient.shutdown();
        }
        return resUrl;
    }

    /**
     * @description: OSS 文件上传
     * @Param: [bytes, fileName]
     * @return: java.lang.String
     * @author: 李东
     * @time: 2020-7-16 16:53
     **/
    public String upload(byte[] bytes, String fileName) {
        log.info("【file-service】文件上传OSS开始,文件名:{}", fileName);
        OSS ossclient = new OSSClientBuilder().build(endpint, accessKeyId, accessKeySecret);
        // 文件上传成功后返回的url
        String resUrl = "";
        try {
            // 容器不存在，就创建
            if (!ossclient.doesBucketExist(bucketName)) {
                ossclient.createBucket(bucketName);
                CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
                createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
                ossclient.createBucket(createBucketRequest);
            }
            // 创建文件路径
            String fileUrl = "files/" + fileName;
            // 上传文件
            ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
            PutObjectResult result = ossclient.putObject(bucketName, fileUrl, inputStream);
            // 设置权限 这里是公开读
            ossclient.setBucketAcl(bucketName, CannedAccessControlList.PublicRead);
            if (null != result) {
                String realUrl = baseUrl + "/" + fileUrl;
                log.info("【file-service】文件上传OSS成功,文件URL地址:{}", realUrl);
                resUrl = realUrl;
            }
        } catch (Exception e) {
            log.error("【file-service】 OSS文件上传异常,异常信息:{}", e);
            throw new RuntimeException("OSS文件上传异常！");
        } finally {
            ossclient.shutdown();
        }
        return resUrl;
    }


    /**
     * @description: 列出指定 bucket 下所有文件
     * @Param: [bucketName]
     * @return: void
     * @author: 李东
     * @time: 2020-7-17 11:20
     **/
    public List<Map<String, String>> listObjects(String bucketName) {
        log.info("【file-service】查询OSS所有文件开始,bucketName is:{}", bucketName);
        OSS ossclient = new OSSClientBuilder().build(endpint, accessKeyId, accessKeySecret);
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);
        ObjectListing objects = ossclient.listObjects(listObjectsRequest);
        log.info("【file-service】查询OSS所有文件返回:{}", objects);
        List<OSSObjectSummary> objectSummaries = objects.getObjectSummaries();
        List<Map<String, String>> files = new ArrayList<>();
        for (OSSObjectSummary summary : objectSummaries) {
            String fileName = summary.getKey().substring(summary.getKey().lastIndexOf("/") + 1);
            Map<String, String> map = new HashMap<>();
            if (!StringUtils.isEmpty(fileName)) {
                map.put("fileName", fileName);
                map.put("fileUrl", baseUrl + "/" + summary.getKey());
                map.put("fileType", DateUtil.date2String(summary.getLastModified()));
                files.add(map);
            }
        }
        log.info("【file-service】封装查询OSS所有文件结果:{}", files);

        return files;
    }

    /**
     * @description: 列出默认 bucket 下所有文件
     * @return: java.util.List<java.util.Map<java.lang.String,java.lang.String>>
     * @author: 李东
     * @time: 2020-7-17 11:51
     **/
    public List<Map<String, String>> listObjects() {
        log.info("【file-service】查询OSS所有文件开始,bucketName is:{}", bucketName);
        OSS ossclient = new OSSClientBuilder().build(endpint, accessKeyId, accessKeySecret);
        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName);
        ObjectListing objects = ossclient.listObjects(listObjectsRequest);
        log.info("【file-service】查询OSS所有文件返回:{}", objects);
        List<OSSObjectSummary> objectSummaries = objects.getObjectSummaries();

        List<Map<String, String>> files = new ArrayList<>();
        for (OSSObjectSummary summary : objectSummaries) {
            String fileName = summary.getKey().substring(summary.getKey().lastIndexOf("/") + 1);
            Map<String, String> map = new HashMap<>();
            if (!StringUtils.isEmpty(fileName)) {
                map.put("fileName", fileName);
                map.put("fileUrl", baseUrl + "/" + summary.getKey());
                map.put("fileType", DateUtil.date2String(summary.getLastModified()));
                files.add(map);
            }
        }
        log.info("【file-service】封装查询OSS所有文件结果:{}", files);

        return files;
    }

}
